/**
 * Copyright (C) 2010  Johan Basson
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

package symorg.io;

import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;
import symorg.midlet.SymOrgMidlet;

/**
 *
 * @author johan
 */
public class FileSelector implements CommandListener {

    public List directoryList;
    private Command openCommand;
    private Command upCommand;
    private Command useCommand;
    private Command cancelCommand;
    private String[] roots = null;
    private SymOrgMidlet application;
    private Displayable backDisplay;
    private String currentDirectory;
    private Image folderIcon;
    private final static String SEP_STR = System.getProperty("file.separator");
    private final static char SEP_CHAR = SEP_STR.charAt(0);
    private final static String ROOT_PREFIX = "file:///";
    private final static String FILE_BROWSER_TITLE = "File Browser";
    private String selectedFileName;

    public FileSelector(SymOrgMidlet midlet, Displayable backDisplay) {
        this.application = midlet;
        this.backDisplay = backDisplay;

        currentDirectory = "";
        openCommand = new Command("Open", Command.OK, 1);
        upCommand = new Command("Up", Command.BACK, 2);
        useCommand = new Command("Use", Command.ITEM, 3);
        cancelCommand = new Command("Cancel", Command.CANCEL, 4);

    }

    private final String[] getRoots() {
        try {
            Enumeration enumeration = FileSystemRegistry.listRoots();
            Vector temp = new Vector();
            String root = "";
            while (enumeration.hasMoreElements()) {
                root = (String) enumeration.nextElement();
                if (true) {
                    temp.addElement(root);
                } else {
                    temp.addElement(root);
                }
            }
            String[] ret = new String[temp.size()];
            temp.copyInto(ret);
            return ret;

        } catch (Exception exception) {
            exception.printStackTrace();
            return null;
        }
    }

    private void printDir(String title, String dir) {
        System.out.println(title + " = " + ROOT_PREFIX + dir);
    }

    private Vector getDirectoryListing(String directory) throws Exception {
        try {
            Vector tempVector;
            String tempString;

            try {
                if (directory.equalsIgnoreCase("")) {
                    if (roots == null) {
                        roots = getRoots();
                        if (roots == null) {
                            return null;
                        }
                    }

                    tempVector = new Vector();
                    for (int i = 0; i < roots.length; i++) {
                        tempVector.addElement(roots[i]);
                    }
                    directoryList.removeCommand(upCommand);

                } else {
                    FileConnection fileConnection = (FileConnection) Connector.open(ROOT_PREFIX + directory, Connector.READ);
                    if (!fileConnection.exists()) {
                        throw new Exception("Cannot open file: " + ROOT_PREFIX + directory);
                    }
                    tempVector = new Vector();
                    for (Enumeration enumer = fileConnection.list(); enumer.hasMoreElements();) {
                        tempString = (String) enumer.nextElement();
                        tempVector.addElement(tempString);
                    }
                    fileConnection.close();
                }
            } catch (Exception exception) {
                throw new Exception(exception.toString());
            }
            return tempVector;
        } catch (Exception e) {
            throw e;
        }
    }

    private void addCommands() {
        directoryList.addCommand(openCommand);
        directoryList.addCommand(upCommand);
        directoryList.addCommand(cancelCommand);
        directoryList.setSelectCommand(useCommand);
        directoryList.setCommandListener(this);

    }

    public void show() throws Exception {
        try {
            directoryList = new List(FILE_BROWSER_TITLE, List.IMPLICIT);
                addCommands();
            Vector dir = getDirectoryListing(currentDirectory);

            for (int i = 0; i < dir.size(); i++) {
                String fname = (String) dir.elementAt(i);
                if (isDirectory(fname)) {
                    directoryList.append(fname, folderIcon);
                }


                if (isFileTypeSupported(fname)) {
                    directoryList.append(fname, null); //image
                }

            }
            application.getDisplay().setCurrent(directoryList);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw ex;
        }
    }

    private boolean isDirectory(String directory) {
        if (directory.charAt(directory.length() - 1) == SEP_CHAR) {
            return true;
        } else {
            return false;
        }
    }

    private String getFileType(String fileName) {
        char ch = '.';
        int index = fileName.lastIndexOf((int) ch);
        return fileName.substring(index + 1);
    }

    private boolean isFileTypeSupported(String fileName) {
        String extension = getFileType(fileName);

        if (extension.equalsIgnoreCase("org")) {
            return true;
        }

        return false;
    }


    public void showError(String message) {
        Form form = new Form("Error");
        form.append(message);
        form.setCommandListener(this);
       // form.addCommand(EXIT);
        application.getDisplay().setCurrent(form);
    }

    public void commandAction(Command c, Displayable d) {
        if (d == directoryList) {
            if (c == openCommand || c.getCommandType() == Command.OK) {
                String selected = directoryList.getString(directoryList.getSelectedIndex());
                currentDirectory += selected;
                if (isDirectory(selected)) {

                    Thread t = new Thread(new Runnable() {

                        public void run() {
                            try {
                                show();
                            } catch (Exception ex) {
                                showError(ex.getMessage() + " "  + currentDirectory);
                                ex.printStackTrace();
                            }
                        }
                    });
                    t.start();

                } else {
                    if (isFileTypeSupported(selected)) {
                        selectedFileName = selected;
                        ((Form) backDisplay).append(currentDirectory);
                        application.getDisplay().setCurrent(backDisplay);
                    }
                }
            } else if (c == upCommand || c.getCommandType() == Command.BACK) {

                Thread t = new Thread(new Runnable() {

                    public void run() {
                        int index = currentDirectory.lastIndexOf(SEP_CHAR);
                        currentDirectory = currentDirectory.substring(0, index);
                        index = currentDirectory.lastIndexOf(SEP_CHAR);
                        currentDirectory = currentDirectory.substring(0, index + 1);
                        try {
                            show();
                        } catch (Exception ex) {
                            showError(ex.getMessage() + " "  + currentDirectory);
                            ex.printStackTrace();
                        }
                    }
                });
                t.start();

            } else if (c == useCommand) {
                Thread t = new Thread(new Runnable() {

                    public void run() {
                        selectedFileName = directoryList.getString(directoryList.getSelectedIndex());
                        currentDirectory += selectedFileName;
                        application.setSelectedFile(currentDirectory);
                        application.outline(-1);
                    }
                });
                t.start();

            } else if (c == cancelCommand) {
                application.getDisplay().setCurrent(backDisplay);
            }

        }
    }

    /**
     * @return the selectedFileName
     */
    public String getSelectedFileName() {
        return selectedFileName;
    }
}
